package node

import (
	"sync"

	"github.com/cihub/seelog"

	iperf "kyland.com/eagle/lib/iperf3"
)

const (
	NODE_ALIVE = "alive"
	NodeAlive  = 1
)

var (
	Mutex        = sync.RWMutex{}
	MinBandwidth = 0.0
)

type Node struct {
	Name           string  `json:"name"`
	Addr           string  `json:"addr"`
	Port           int     `json:"port"`
	LastUpdateTime int64   `json:"last_update_time"`
	Error          string  `json:"error"`
	Status         string  `json:"status"`
	Bandwidth      float64 `json:"bandwidth"`
}

var (
	Localhost string
	NodesMap  map[string]int
)

func GetSufficientBandwidthNodes() []*Node {
	nodeList := make([]*Node, 0)

	seelog.Infof("current min bandwidth is %f", MinBandwidth)

	Mutex.RLock()
	defer Mutex.RUnlock()
	for addr, status := range NodesMap {
		if status == NodeAlive && addr != Localhost {
			retry := 1
			var result *iperf.Iperf3Stream
			var err error
			for retry <= 2 {
				result, err = iperf.NewIperf3().GetOutboundBandwidth(addr)
				if err != nil {
					seelog.Errorf("failed to query node %s bandwidth, retry: %d, error: %v", addr, retry, err)
					retry++
					continue
				}
				break
			}

			if result != nil {
				bandwidth := result.Receiver.BitsPerSecond / 1024 / 1024
				seelog.Infof("node %s bandwidth is %0.2f", addr, bandwidth)
				if bandwidth >= MinBandwidth {
					nodeList = append(nodeList, &Node{
						Addr:      addr,
						Bandwidth: bandwidth,
					})
					continue
				} else {
					seelog.Infof("the node %s bandwidth %0.2f is less than %0.2f Mbit/s,cannot be used for scheduling tasks.", addr, bandwidth, MinBandwidth)
				}
			}
		}
	}

	return nodeList
}